#include "app_led.h"

#define RED_LED_TOGGLE_COUNTS_MAX   (40)

typedef struct {
    app_led_state_t state;
    unsigned int interval;	
    unsigned int stop;			
    unsigned int next;
    unsigned char counts;
} app_led_mgr_t;

volatile static app_led_mgr_t led_mgr[APP_LED_MAX] = {0x00};



void app_led_init(void)
{
	drv_led_init();
	//app_led_toggle(APP_LED_UNLOCK, APP_TOGGLE_FAST_TIME, 0);
	//app_led_toggle(APP_LED_LOCK, APP_TOGGLE_FAST_TIME, 0);
    //app_led_toggle(APP_LED_WIFI, APP_TOGGLE_FAST_TIME, 0);
	//app_led_toggle(APP_LED_BAT, APP_TOGGLE_FAST_TIME, 0);
    //app_led_toggle(APP_LED_JAM, APP_TOGGLE_FAST_TIME, 0);
	//app_led_toggle(APP_LED_FEED, APP_TOGGLE_FAST_TIME, 0);
	//app_led_toggle(APP_LED_RESET, APP_TOGGLE_FAST_TIME, 0);
    //app_led_on(APP_LED_FEED);
    //app_led_on(APP_LED_RESET);
}

void app_led_task(void)
{
    for (unsigned char i = 0; i < APP_LED_MAX; i++) {
        if (led_mgr[i].state != APP_LED_TOGGLE) {
            continue;
        }
        if (time_after(app_sys_ticks, led_mgr[i].next)) {
						drv_led_toggle((drv_led_t)i);
            led_mgr[i].next = app_sys_ticks + led_mgr[i].interval;
        }
    }
}
void app_led_toggle(app_led_type_t type, unsigned int interval, unsigned int timeout)
{
    ret_if_true(type == APP_LED_MAX)

    // @note 当电源电压低 时，红灯不再闪烁
//    if (type == APP_LED_RED && app_power_is_low_level()) {
//        app_led_off(APP_LED_RED);
//        return ;
//    } 

    if (led_mgr[type].state != APP_LED_TOGGLE) {
        drv_led_t led = (drv_led_t)type;
        drv_led_toggle(led);
        led_mgr[type].next      = app_sys_ticks + interval;
    }

    led_mgr[type].counts    = 0x00;
    led_mgr[type].state     = APP_LED_TOGGLE;
    led_mgr[type].interval  = interval;
    led_mgr[type].stop      = app_sys_ticks + timeout;
}

void app_led_on(app_led_type_t type)
{
    ret_if_true(type == APP_LED_MAX)

    // @note 当电源电压低 时，红灯不再亮起
//    if (type == APP_LED_RED && app_power_is_low_level()) {
//        app_led_off(APP_LED_RED);
//        return ;
//    } 

    drv_led_t led = (drv_led_t)type;
    drv_led_set(led, DRV_LED_ON);

    led_mgr[type].state     = APP_LED_ON;
    led_mgr[type].interval  = 0x00;
    led_mgr[type].stop      = 0x00;
    led_mgr[type].next      = 0x00;
}

void app_led_off(app_led_type_t type)
{
    ret_if_true(type == APP_LED_MAX)

    drv_led_t led = (drv_led_t)type;
    drv_led_set(led, DRV_LED_OFF);

    led_mgr[type].state     = APP_LED_OFF;
    led_mgr[type].interval  = 0x00;
    led_mgr[type].stop      = 0x00;
    led_mgr[type].next      = 0x00;
}

void app_led_on_all(void)
{
    for (unsigned char i = 0; i < APP_LED_MAX; i++) {
        drv_led_set(i, DRV_LED_ON);
    }
}

void app_led_off_all(void)
{
    for (unsigned char i = 0; i < APP_LED_MAX; i++) {
        drv_led_set(i, DRV_LED_OFF);
    }
}

void app_led_timer_init(void)
{
    LL_TIM_InitTypeDef TIM_InitStruct = {0x00};
    LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_TIM16);
    TIM_InitStruct.ClockDivision        = LL_TIM_CLOCKDIVISION_DIV1;
    TIM_InitStruct.CounterMode          = LL_TIM_COUNTERMODE_UP;
    TIM_InitStruct.Prescaler            = 24 - 1;
    TIM_InitStruct.Autoreload           = 40000 - 1;
    TIM_InitStruct.RepetitionCounter    = 0;
    LL_TIM_Init(TIM16, &TIM_InitStruct);
    
    NVIC_SetPriority(TIM16_IRQn,3);
    LL_TIM_SetCounter(TIM16, 0x00);
    LL_TIM_EnableIT_UPDATE(TIM16);
    LL_TIM_EnableCounter(TIM16);
    NVIC_EnableIRQ(TIM16_IRQn);
}

void app_led_timer_deinit(void)
{
    NVIC_DisableIRQ(TIM16_IRQn);
    LL_TIM_DisableCounter(TIM16);
    LL_TIM_DeInit(TIM16);
}

void app_led_timer_irq_handler(void)
{
    app_led_task();
}

unsigned char app_led_toggle_is_stopped(void)
{
    if (led_mgr[APP_LED_BAT].state == APP_LED_OFF) {
        return 0x01;
    }

    return 0x00;
}
